package com.th.apicenter.config;

import com.th.apicenter.deduct.entity.ThApiLogs;
import com.th.apicenter.mapper.ThApiLogsMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;

@Aspect
@Component
@Slf4j
public class ThLogAspect {

    @Resource
    private ThApiLogsMapper thApiLogsMapper;

    // 定义切点：拦截所有被 @ThLog 注解的方法
    @Pointcut("@annotation(com.th.apicenter.config.ThLog)")
    public void loggableMethod() {
    }

    @Around("loggableMethod() && @annotation(thLog)")
    public Object logAround(ProceedingJoinPoint joinPoint, ThLog thLog) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        Object[] args = joinPoint.getArgs();

        // 记录方法开始日志
        logMessage(thLog.level(), "Entering method [{}] with args: {}", methodName, args);
        ThApiLogs thApiLogs = new ThApiLogs();
        thApiLogs.setType(thLog.type());
        StopWatch stopWatch = null;
        if (thLog.trackTime()) {
            stopWatch = new StopWatch();
            stopWatch.start();
        }

        try {
            Object result = joinPoint.proceed(); // 执行目标方法

            // 记录方法结束日志
            if (thLog.trackTime()) {
                stopWatch.stop();
                logMessage(thLog.level(), "Exiting method [{}] with result: {} (Execution time: {} ms)",
                        methodName, result, stopWatch.getTotalTimeMillis());
            } else {
                logMessage(thLog.level(), "Exiting method [{}] with result: {}", methodName, result);
            }

            return result;
        } catch (Throwable e) {
            // 记录异常日志
            log.error("Exception in method [{}]: {}", methodName, e.getMessage());
            throw e;
        }
    }

    // 统一处理日志级别
    private void logMessage(ThLog.LogLevel level, String message, Object... args) {
        switch (level) {
            case DEBUG:
                log.debug(message, args);
                break;
            case WARN:
                log.warn(message, args);
                break;
            case ERROR:
                log.error(message, args);
                break;
            default:
                log.info(message, args);
        }
    }

}
